package com.cooqe.collection_snmp.utils;

import com.cooqe.collection_snmp.model.SnmpParameter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.UserTarget;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import java.io.IOException;

/**
 * @author 折戟沉沙铁未销
 * @version V1.0
 * @date 2023/11/14-2023
 * @Description: snmp util 工具类
 */
@Slf4j
public class SnmpUtil {

    //定义常量
    public static final String AES256 = "aes256";
    public static final String AES192 = "aes192";
    public static final String AES128 = "aes128";
    public static final String _3DES = "3des";
    public static final String DES = "des";
    public static final String SHA = "sha";
    public static final String MD5 = "md5";

    //初始化 snmp 对象
    public static Snmp createSnmp(){
        Snmp snmp = null;
        try {
            DefaultUdpTransportMapping transportMapping = new DefaultUdpTransportMapping();
            transportMapping.setReceiveBufferSize(50 * 1024 * 1024);

            USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(
                    MPv3.createLocalEngineID(new OctetString("MyUniqueID" + System.currentTimeMillis()))),
                    0);

            snmp = new Snmp();
            snmp.addTransportMapping(transportMapping);
            SecurityProtocols.getInstance().addDefaultProtocols();
            snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
            snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
            snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3(usm));
            snmp.getMessageDispatcher().addCommandResponder(snmp);
            snmp.listen();
        } catch (IOException e) {
            log.warn(e.getMessage());
        }
        return snmp;
    }

    //创建 target 对象
    @SuppressWarnings("all")
    public static Target createTarget(SnmpParameter p, Snmp snmp) {
        // v3 版本的
        if (p.getVersion() == SnmpConstants.version3) {
            UserTarget target = new UserTarget();
            target.setSecurityLevel(p.getSecurityLevel());
            OctetString securityName = new OctetString(p.getSecurityName());
            OctetString authPassphrase = null;
            OctetString privacyPassphrase = null;
            OID authProtocol = null;
            OID privacyProtocol = null;
            // 认证加密
            if (StringUtils.isNotBlank(p.getAuthPassphrase()) && p.getSecurityLevel() != SecurityLevel.NOAUTH_NOPRIV) {
                authPassphrase = new OctetString(p.getAuthPassphrase());
                if (StringUtils.equalsIgnoreCase(p.getAuthProtocol(), MD5)) {
                    authProtocol = AuthMD5.ID;
                }
                else if (StringUtils.equalsIgnoreCase(p.getAuthProtocol(), SHA)) {
                    authProtocol = AuthSHA.ID;
                }
            }
            // 加密算法
            if (StringUtils.isNotBlank(p.getPrivacyPassphrase()) && p.getSecurityLevel() == SecurityLevel.AUTH_PRIV) {
                privacyPassphrase = new OctetString(p.getPrivacyPassphrase());
                if (StringUtils.equalsIgnoreCase(p.getPrivacyProtocol(), DES)) {
                    privacyProtocol = PrivDES.ID;
                }
                else if (StringUtils.equalsIgnoreCase(p.getPrivacyProtocol(), _3DES)) {
                    privacyProtocol = Priv3DES.ID;
                }
                else if (StringUtils.equalsIgnoreCase(p.getPrivacyProtocol(), AES128)) {
                    privacyProtocol = PrivAES128.ID;
                }
                else if (StringUtils.equalsIgnoreCase(p.getPrivacyProtocol(), AES192)) {
                    privacyProtocol = PrivAES192.ID;
                }
                else if (StringUtils.equalsIgnoreCase(p.getPrivacyProtocol(), AES256)) {
                    privacyProtocol = PrivAES256.ID;
                }
            }
            target.setSecurityName(securityName);
            UsmUser user = new UsmUser(securityName, authProtocol, authPassphrase, privacyProtocol, privacyPassphrase);
            snmp.getUSM().addUser(securityName, user);
            return target;
        }

        // snmp v1 or v2c
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(p.getCommunity()));

        // snmp agent 地址
        Address address = new UdpAddress(p.getIp() + "/" + p.getPort());
        target.setAddress(address);
        // 通信不成功时的重试次数
        target.setRetries(p.getSnmpRetry());
        // 超时时间
        target.setTimeout(p.getSnmpTimeout());
        // 版本
        target.setVersion(p.getVersion());

        //返回
        return target;
    }
}